﻿#include "framework.h"
#include "MainWindow.h"
#include "Resource.h"

// 函数声明
static void MainWindow_Delete(MainWindow*);
static void MainWindow_DoModal(MainWindow*);
static void MainWindow_OnButtonStartClicked(MainWindow*);
static void MainWindow_OnGameOver(MainWindow*, BOOL);
static BOOL MainWindow_OnKeyPressed(MainWindow*, UINT);
static INT_PTR CALLBACK MainWindow_Proc(HWND, UINT, WPARAM, LPARAM);

/**
 * 创建主窗口。
 * @return 主窗口
 */
MainWindow* New_MainWindow() {
    MainWindow* mainWindow = (MainWindow*)calloc(1, sizeof(MainWindow));

    // 初始化数据
    mainWindow->mHandle = CreateDialog(NULL, MAKEINTRESOURCE(IDD_MAIN_WINDOW), NULL, MainWindow_Proc);
    SetWindowLongPtr(mainWindow->mHandle, GWLP_USERDATA, (LONG_PTR)mainWindow);

    // 初始化函数
    mainWindow->doModal = MainWindow_DoModal;

    // 创建游戏区域
    mainWindow->mGameBoard = New_GameBoard(mainWindow->mHandle, GAME_BOARD_X, GAME_BOARD_Y, GAME_BOARD_WIDTH, GAME_BOARD_HEIGHT);

    // 创建游戏
    mainWindow->mGame = New_Game(mainWindow->mHandle, mainWindow->mGameBoard->mDrawer, mainWindow->mGameBoard->mHandle);

    return mainWindow;
}

/**
 * 删除主窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_Delete(MainWindow* mainWindow) {
    mainWindow->mGame->deleteSelf(mainWindow->mGame);
    mainWindow->mGameBoard->deleteSelf(mainWindow->mGameBoard);
    DestroyWindow(mainWindow->mHandle);
    free(mainWindow);
}

/**
 * 以模态显示窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_DoModal(MainWindow* mainWindow) {
    MSG msg = { 0 };
    BOOL handledKeyPress = FALSE;

    // 显示窗口
    ShowWindow(mainWindow->mHandle, SW_SHOW);

    // 窗口事件循环
    while (GetMessage(&msg, NULL, 0, 0)) {
        if (msg.message == WM_KEYDOWN) {
            handledKeyPress = MainWindow_OnKeyPressed(mainWindow, (UINT)msg.wParam);
        }
        if (!handledKeyPress) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        handledKeyPress = FALSE;
    }
}

/**
 * "开始"按钮的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnButtonStartClicked(MainWindow* mainWindow) {
    TCHAR text[STRING_BUF_LEN] = { 0 };
    LoadString(NULL, IDS_RESTART, text, STRING_BUF_LEN);
    SetDlgItemText(mainWindow->mHandle, IDC_BUTTON_START, text);

    mainWindow->mGame->start(mainWindow->mGame);
}

/**
 * 游戏结束事件的响应函数。
 * @param mainWindow    主窗口
 * @param isWon         胜利则为 TRUE，否则为 FALSE
 */
static void MainWindow_OnGameOver(MainWindow* mainWindow, BOOL isWon) {
    TCHAR text[STRING_BUF_LEN] = { 0 };

    if (isWon) {
        LoadString(NULL, IDS_WON, text, STRING_BUF_LEN);
    } else {
        LoadString(NULL, IDS_LOST, text, STRING_BUF_LEN);
    }
    MessageBox(mainWindow->mHandle, text, _T(" "), MB_ICONINFORMATION);

    LoadString(NULL, IDS_START, text, STRING_BUF_LEN);
    SetDlgItemText(mainWindow->mHandle, IDC_BUTTON_START, text);
}

/**
 * 按键事件的响应函数。
 * @param mainWindow    主窗口
 * @param key           按键
 * @return 事件在这此被处理则返回 TRUE，否则返回 FALSE
 */
static BOOL MainWindow_OnKeyPressed(MainWindow* mainWindow, UINT key) {
    return mainWindow->mGame->onKeyPressed(mainWindow->mGame, key);
}

/**
 * 窗口过程函数。
 * @param window    窗口
 * @param message   事件标识
 * @param wParam    事件相关信息
 * @param lParam    事件相关信息
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static INT_PTR CALLBACK MainWindow_Proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    MainWindow* mainWindow = (MainWindow*)GetWindowLongPtr(window, GWLP_USERDATA);
    WORD id = LOWORD(wParam);
    UNREFERENCED_PARAMETER(lParam);

    switch (message) {
        case UM_GAME_OVER:
            MainWindow_OnGameOver(mainWindow, (BOOL)wParam);
            return TRUE;
        case WM_COMMAND:
            switch (id) {
                case IDC_BUTTON_START:
                    MainWindow_OnButtonStartClicked(mainWindow);
                    return TRUE;
                case IDCANCEL:
                    MainWindow_Delete(mainWindow);
                    return TRUE;
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            return TRUE;
    }
    return FALSE;
}
